package org.happycomp.radio.downloader;

import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;

import org.happycomp.radio.PlaylistEntry;
import org.happycomp.radio.ProcessStates;
import org.happycomp.radio.ProcessUnit;
import org.happycomp.radio.StopDownloadCondition;
import org.happycomp.radio.StoreStateException;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class DownloadingItem implements ProcessUnit{ 
	
	public static final java.util.logging.Logger LOGGER = java.util.logging.Logger
			.getLogger(DownloadingItem.class.getName());
	
	private PlaylistEntry playlistEntry;
	
	private File file;
	private File[] previousFiles;
	
	private String id;
	private String title;
	private Date date;
	private String processPid;
	private ProcessStates state = ProcessStates.DOWNLOADING;
	private StopDownloadCondition condition;
	
	private boolean persistedItem = false;

	public static final String PATTERN ="yyyy-MM-dd'T'HH:mm:ss.SSSZ";
	
	public DownloadingItem(File nfile, String id, String title, PlaylistEntry entry, Date date, String processPid,StopDownloadCondition condition) {
		super();
		this.file = nfile;
		this.id = id;
		this.playlistEntry = entry;
		this.date = date;
		this.processPid = processPid; 
		this.title = title;
		this.condition = condition;
	}


	
	DownloadingItem() {
		super();
	}


	public String getProcessPid() {
		return processPid;
	}



	protected void setProcessPid(String processPid) {
		this.processPid = processPid;
	}



	protected void setFile(File file) {
		this.file = file;
	}



	protected void setId(String id) {
		this.id = id;
	}



	protected void setDate(Date date) {
		this.date = date;
	}



	public File getFile() {
		return file;
	}



	public String getId() {
		return id;
	}
	
	
	public PlaylistEntry getPlaylistEntry() {
		return playlistEntry;
	}

	
	public Date getDate() {
		return date;
	}

	
	public ProcessStates getProcessState() {
		return state;
	}

	public StopDownloadCondition geStopDownloadingCondition() {
		return this.condition;
	}

	public void setState(ProcessStates state) {
		this.state = state;
	}

	
	protected void setPlaylistEntry(PlaylistEntry playlistEntry) {
		this.playlistEntry = playlistEntry;
	}

	public String getTitle() {
		return title;
	}

	
	public void setPreviousFiles(File[] previousFiles) {
		this.previousFiles = previousFiles;
	}
	
	public File[] getPreviousFiles() {
		return previousFiles;
	}
	
	
	public StopDownloadCondition getStopDownloadCondition() {
		return this.condition;
	}
	
	void setStopDownloadCondition(StopDownloadCondition condition) {
		this.condition = condition;
	}
	
	public static DownloadingItem loadFromElement(Element elm, StopDownloadCondition condition) throws StoreStateException {
		if (elm.getNodeName().equals("downloadingItem")) {
			try {
				Date startDate = null;
				Date stopDate = null;
				
				DownloadingItem item = new DownloadingItem();
				item.setPersistedItem(true);
				NodeList childNodes = elm.getChildNodes();
				for (int i = 0,ll=childNodes.getLength(); i < ll; i++) {
					Node node = childNodes.item(i);
					if (node.getNodeType() == Node.ELEMENT_NODE) {
						String name = node.getNodeName();
						if (name.equals("id")) {
							item.setId(node.getTextContent());
						}
						if (name.equals("file")) {
							item.setFile(new File(node.getTextContent()));
						}
						if (name.equals("title")) {
							item.setTitle(node.getTextContent());
						}
						
						if (name.equals("stopDate")) {
							stopDate = new SimpleDateFormat(DownloadingItem.PATTERN).parse(node.getTextContent());
						}

						if (name.equals("previousFiles")) {
							String paths = node.getTextContent();
							String[] filePaths = paths.split(",");
							File[] files = new File[filePaths.length];
							for (int j = 0; j < files.length; j++) {
								files[j] = new File(filePaths[j]);
							}
						}

						if (name.equals("pid")) {
							item.setProcessPid(node.getTextContent());
						}
						if (name.equals("id")) {
							item.setId(node.getTextContent());
						}
						if (name.equals("date")) {
							startDate = new SimpleDateFormat(DownloadingItem.PATTERN).parse(node.getTextContent());
							item.setDate(startDate);
						}
						if (name.equals("state")) {
							ProcessStates state = ProcessStates.valueOf(node.getTextContent());
							item.setState(state);
						}
						if (name.equals("playlist")) {
							PlaylistEntry entry = PlaylistEntry.loadFromElement((Element)node);
							item.setPlaylistEntry(entry);
						}
					}
				}
				initStopCondition(item, condition, startDate, stopDate);
				return item;
			} catch (DOMException e) {
				LOGGER.log(Level.SEVERE, e.getMessage(), e);
			} catch (ParseException e) {
				LOGGER.log(Level.SEVERE, e.getMessage(), e);
			}
		}
		return null;
	}


	static void initStopCondition(DownloadingItem itm, StopDownloadCondition condition, Date startDate, Date stopDate) {
		LOGGER.fine("Initializing stop condition");
		condition.initFromStopDate(startDate, stopDate);
		itm.setStopDownloadCondition(condition);
	}
	
	void setTitle(String title) {
		this.title = title;
	}



	public Element storeElement(Document document) {
		Element root = document.createElement("downloadingItem");

		Element idElement = document.createElement("id");
		idElement.setTextContent(this.id);
		root.appendChild(idElement);

		Element fileElement = document.createElement("file");
		fileElement.setTextContent(this.file.getAbsolutePath());
		root.appendChild(fileElement);

		Element titleElement = document.createElement("title");
		titleElement.setTextContent(this.title);
		root.appendChild(titleElement);

		Element pidElement = document.createElement("pid");
		pidElement.setTextContent(this.processPid);
		root.appendChild(pidElement);
 
		Element dateElement = document.createElement("date");
		dateElement.setTextContent(new SimpleDateFormat(DownloadingItem.PATTERN).format(this.date));
		root.appendChild(dateElement);

		
		Element stateElement = document.createElement("state");
		stateElement.setTextContent(state.name());
		root.appendChild(stateElement);

		StopDownloadCondition condition = getStopDownloadCondition();
		Element stopDateElement = document.createElement("stopDate");
		Date stopDate = condition.storeToStopDate(getDate());
		stopDateElement.setTextContent(new SimpleDateFormat(DownloadingItem.PATTERN).format(stopDate));
		root.appendChild(stopDateElement);
		
		
		if ((previousFiles != null) && (previousFiles.length > 0)) {
			Element previousFilesElement = document.createElement("previousFiles");
			StringBuffer buff = new StringBuffer();
			for (int i = 0; i < previousFiles.length; i++) {
				buff.append(previousFiles[i].getAbsolutePath());
				if (i < previousFiles.length -1) buff.append(',');
			}
			previousFilesElement.setTextContent(buff.toString());
			root.appendChild(previousFilesElement);
		}

		root.appendChild(this.playlistEntry.storeElement(document));
		
		return root;
	}



	@Override
	public String toString() {
		return "'"+this.title+"' "+this.file.getAbsolutePath() + getChain() ;
	}
	
	public String getChain() {
		if ((previousFiles != null) && (this.previousFiles.length > 0)) {
			StringBuffer buff = new StringBuffer("  (");
			for (File chainFile : this.previousFiles) {
				buff.append(chainFile.getAbsolutePath()).append(" ");
			}
			buff.append(")");
			return buff.toString();
		} else {
			return "";
		}
	}



	public boolean isPersistedItem() {
		return persistedItem;
	}



	public void setPersistedItem(boolean persistedItem) {
		this.persistedItem = persistedItem;
	}
	
	
}
